package cc.magicjson.interceptor;

import cc.magicjson.GracefulShutdownApplication;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import java.io.IOException;

@Component
public class PortInterceptor implements HandlerInterceptor {

	@Value("${server.default-port}")
	private int defaultPort;

	@EventListener(ApplicationReadyEvent.class)
	public void onApplicationReady() {
		int port = Integer.parseInt(System.getProperty("server.port"));
		if (port != defaultPort) {
			killProcessUsingPort(defaultPort);
			restartOnDefaultPort();
		}
	}

	private void killProcessUsingPort(int port) {
		String os = System.getProperty("os.name").toLowerCase();
		String command;

		if (os.contains("win")) {
			command = String.format("cmd /c netstat -ano | findstr :%d | findstr LISTENING", port);
			try {
				Process process = Runtime.getRuntime().exec(command);
				process.waitFor();
				String output = new String(process.getInputStream().readAllBytes());
				String[] lines = output.split("\n");
				for (String line : lines) {
					if (line.contains("LISTENING")) {
						String pid = line.trim().split("\\s+")[4];
						Runtime.getRuntime().exec("cmd /c taskkill /PID " + pid + " /F");
						System.out.println("Killed process with PID: " + pid + " using port: " + port);
					}
				}
			} catch (IOException | InterruptedException e) {
				e.printStackTrace();
				throw new RuntimeException("Failed to kill process using port " + port, e);
			}
		} else {
			command = String.format("lsof -t -i:%d | xargs kill -9", port);
			try {
				Runtime.getRuntime().exec(new String[]{"bash", "-c", command});
				System.out.println("Killed process using port: " + port);
			} catch (IOException e) {
				e.printStackTrace();
				throw new RuntimeException("Failed to kill process using port " + port, e);
			}
		}
	}

	private void restartOnDefaultPort() {
//		System.setProperty("server.port", String.valueOf(defaultPort));
		SpringApplication.run(GracefulShutdownApplication.class);
	}
}
